﻿using System.Collections.Generic;
using Flatland.GeneticProgramming.CoreTypes;

/**
* 
* Copyright (c) 2012 Anders Høst Kjærgaard | ahkj@itu.dk
* 
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, 
* including without limitation the rights to use, copy, modify, merge, publish, distribute, 
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial 
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

namespace Flatland.GeneticProgramming.Mutations {

    /// <summary>
    /// Mutation strategy. Add a new strategy by defining a related enum and provide the IMutation implementation type
    /// </summary>
    public enum MutationTechnique {
        [GPTechnique(typeof(NodeReplacement))]
        Node_Replacement,

        [GPTechnique(typeof(SubtreeMutation))]
        Subtree_Replacement,
    };

    /// <summary>
    /// Mutation class serves as a proxy to the chosen mutationstrategy implementation.
    /// </summary>
    public class Mutation : IMutation {

        /// <summary>
        /// IMutation implementation.
        /// </summary>
        private IMutation _mutation;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="mutationTechnique"></param>
        public Mutation(MutationTechnique mutationTechnique) {
            _mutation = (IMutation)GPTechnique.GetImplementer(typeof(MutationTechnique), (int)mutationTechnique);
        }

        /// <summary>
        /// Apply mutation to a population
        /// </summary>
        /// <param name="reports">The reports for genes to be mutated</param>
        /// <param name="mutationRate">Mutation rate</param>
        public void Mutate(List<Report> reports, double mutationRate, int maxTreeDepth) {
            _mutation.Mutate(reports, mutationRate, maxTreeDepth);
        }
    }
}